package net.homeip.mmhg.dao;

import java.util.Collection;
import java.util.List;

import net.homeip.mmhg.domain.Role;
import net.homeip.mmhg.domain.Team;

import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Subqueries;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Hibernate implementation of <code>TeamDao</code> interface.
 *
 * @author ilya gerasimov
 */
@Repository
public class TeamDaoImpl implements TeamDao {

	private HibernateTemplate template;
	
	private static String ADMINISTRATOR = "ADMINISTRATOR";
	private static String USER = "USER";

	@Autowired
	public void setHibernateTemplate(SessionFactory sessionFactory) {
		this.template = new HibernateTemplate(sessionFactory);
	}
	
	@Override
	@Transactional(readOnly = true)
	public Team getTeam(int id) {
		return (Team) template.get(Team.class, id);
	}
	
	@Override
	@Transactional(readOnly = true)
	public Collection<Team> getTeams() {
		return findByRole(USER);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	@Transactional(readOnly = true)
	public Team getTeam(String name) {
		DetachedCriteria criteria = DetachedCriteria.forClass(Team.class)
													.add(Property.forName("name").eq(name));
		List<Team> resultList = template.findByCriteria(criteria);
		if ((resultList != null) && resultList.size() != 0) {
			return resultList.get(0);
		} else {
			return null;
		}
	}

	@Override
	@Transactional(readOnly = true)
	public Collection<Team> getAdmins() {
		return findByRole(ADMINISTRATOR);
	}
	
	@SuppressWarnings("unchecked")
	private Collection<Team> findByRole(String role) {
		DetachedCriteria criteria = DetachedCriteria.forClass(Team.class)
													.add(Subqueries.propertyIn("role", DetachedCriteria.forClass(Role.class)
															.setProjection(Projections.property("id"))
															.add(Property.forName("name").eq(role))));
		return template.findByCriteria(criteria);
	}

}
